﻿using Future.Common.Enum;
using Future.IBLL;
using Future.IDAL;
using Future.Model.DtoModel;
using Future.Model.SysModel;
using Future.Model.ViewModel;

namespace Future.BLL
{
    /// <summary>
    /// 描述：菜单业务逻辑类
    /// 创建人： yangkai
    /// 创建时间：2022/11/15 22:05:49
    /// </summary>
    public class MenuBLL : IMenuBLL
    {
        private readonly IMenuDAL _menuDAL;
        private readonly IRoleMenuDAL _roleMenuDAL;

        public MenuBLL(IMenuDAL menuDAL, IRoleMenuDAL roleMenuDAL)
        {
            _menuDAL = menuDAL;
            _roleMenuDAL = roleMenuDAL;
        }

        public bool CreateMenu(MenuModel menuModel)
        {
            menuModel.Id = Guid.NewGuid();
            return _menuDAL.Insert(menuModel);
        }

        public bool DeleteMenu(Guid id)
        {
            return _menuDAL.Delete(x => x.Id == id);
        }

        public List<VueRouterVo> GetAllMenus(Guid userId, bool isAdmin)
        {
            List<MenuModel> menuModels;
            if (isAdmin)
            {
                menuModels = _menuDAL.GetList(x => x.Visible);
            }
            else
            {
                menuModels = _menuDAL.GetMenusByUserId(userId);
            }
            return RouterBuild(menuModels);
        }

        public List<MenuModel> GetListByRoleId(Guid roleId)
        {
            List<MenuModel> menuModels = new();
            List<RoleMenuModel> roleMenuModels = _roleMenuDAL.GetList(x => x.RoleId == roleId);
            if (!roleMenuModels.Any())
            {
                return menuModels;
            }

            IEnumerable<Guid> menuIds = roleMenuModels.Select(x => x.MenuId);
            menuModels = _menuDAL.GetList(x => menuIds.Contains(x.Id) && x.Visible);
            return menuModels;
        }

        public MenuModel GetMenuById(Guid id)
        {
            return _menuDAL.Get(x => x.Id == id);
        }

        public List<MenuModel> GetMenuList(MenuQueryDto menuQueryDto)
        {
            List<MenuModel> reulst = _menuDAL.GetMenuList(menuQueryDto);
            reulst = reulst.OrderBy(x => x.OrderNum).ToList();
            return reulst;
        }

        public List<MenuModel> GetMenusByUserId(Guid userId)
        {
            return _menuDAL.GetMenusByUserId(userId);
        }

        public bool Update(MenuModel menuModel)
        {
            return _menuDAL.Update(menuModel);
        }

        /// <summary>
        /// 装换模型变成树状结构
        /// </summary>
        /// <param name="menuModels"></param>
        /// <returns></returns>
        private List<VueRouterVo> RouterBuild(IEnumerable<MenuModel> menuModels)
        {
            menuModels = menuModels.Where(m => m.MenuType != MenuTypeEnum.Component);
            List<VueRouterVo> routers = new();
            //模型转换
            foreach (var menu in menuModels)
            {

                VueRouterVo vueRouter = new()
                {
                    OrderNum = menu.OrderNum
                };
                string routerName = menu.Router.Split("/", StringSplitOptions.RemoveEmptyEntries).Last();
                vueRouter.Id = menu.Id;
                vueRouter.ParentId = menu.ParentId;

                //开头大写
                vueRouter.Name = string.Concat(routerName.First().ToString().ToUpper(), routerName.AsSpan(1));
                vueRouter.Path = menu.Router;
                vueRouter.Hidden = !menu.Visible;


                if (menu.MenuType == MenuTypeEnum.Catalogue)
                {
                    vueRouter.Redirect = "noRedirect";
                    vueRouter.AlwaysShow = true;

                    //判断是否为最顶层的路由
                    if (!menu.ParentId.HasValue)
                    {
                        vueRouter.Component = "Layout";
                    }
                    else
                    {
                        vueRouter.Component = "ParentView";
                    }
                }

                if (menu.MenuType == MenuTypeEnum.Menu)
                {

                    vueRouter.Redirect = "noRedirect";
                    vueRouter.Component = menu.Component;
                    vueRouter.AlwaysShow = false;
                }

                vueRouter.Meta = new Meta
                {
                    Title = menu.MenuName,
                    Icon = menu.Icon,
                    NoCache = true
                };

                if (menu.IsLink.HasValue && menu.IsLink.Value)
                {
                    vueRouter.Meta.Link = menu.Router;
                    vueRouter.AlwaysShow = false;
                }

                routers.Add(vueRouter);
            }

            IEnumerable<VueRouterVo> result = routers.Where(x => !x.ParentId.HasValue).OrderBy(x => x.OrderNum);
            SetTreeChildren(result, routers);
            return result.ToList();
        }

        /// <summary>
        /// 递归生成子节点
        /// </summary>
        /// <param name="parents"></param>
        /// <param name="routers"></param>
        private void SetTreeChildren(IEnumerable<VueRouterVo> parents, IEnumerable<VueRouterVo> routers)
        {
            foreach (VueRouterVo parent in parents)
            {
                IEnumerable<VueRouterVo> children = routers.Where(x => x.ParentId == parent.Id);
                if (children.Any())
                {
                    parent.Children = children.OrderBy(x => x.OrderNum).ToList();
                    SetTreeChildren(parent.Children, routers);
                }
            }
        }
    }
}
